package com.gsi.webstore.platform.storefront.pipelet.inventory;

import java.util.List;
import java.util.Map;

import com.gsi.webstore.platform.adapter.inventory.multichannel.capi.MultichannelInventoryService;
import com.gsi.webstore.platform.adapter.inventory.multichannel.data.InStoreQuantityRequest;
import com.gsi.webstore.platform.adapter.inventory.multichannel.data.InStoreQuantityResponse;
import com.gsi.webstore.platform.adapter.inventory.multichannel.internal.MultichannelInventoryServiceResolver;
import com.gsi.webstore.platform.adapter.storelocator.internal.client.data.Storefront;
import com.intershop.beehive.core.capi.component.ComponentMgr;
import com.intershop.beehive.core.capi.domain.Domain;
import com.intershop.beehive.core.capi.log.Logger;
import com.intershop.beehive.core.capi.naming.NamingMgr;
import com.intershop.beehive.core.capi.pipeline.Pipelet;
import com.intershop.beehive.core.capi.pipeline.PipeletExecutionException;
import com.intershop.beehive.core.capi.pipeline.PipelineDictionary;
import com.intershop.beehive.xcs.capi.product.Product;
import com.intershop.component.organization.capi.Organization;

/**
 * Creates a request to retrieve store front inventory levels for multiple
 * storefronts.
 */
public class StorefrontQuantityRequest extends Pipelet
{

    /**
     * Constant used to access the pipeline dictionary with key 'StorefrontQuantityMap'
     * 
     * Map of storefront ids to inventory quantities
     */
    public static final String DN_STOREFRONT_QUANTITY_MAP = "StorefrontQuantityMap";
   
    /**
     * Constant used to access the pipeline dictionary with key 'CurrentOrganization'
     */
    public static final String DN_CURRENT_ORGANIZATION = "CurrentOrganization";
    /**
     * Constant used to access the pipeline dictionary with key 'StoreList'
     * 
     * List of storefront objects
     */
    public static final String DN_STORE_FRONTS = "StoreFronts";
    /**
     * Constant used to access the pipeline dictionary with key 'Quantity'
     */
    public static final String DN_QUANTITY = "Quantity";
    /**
     * Constant used to access the pipeline dictionary with key 'Product'
     */
    public static final String DN_PRODUCT = "Product";

    /**
     * The pipelet's execute method is called whenever the pipelets gets
     * executed in the context of a pipeline and a request. The pipeline
     * dictionary valid for the currently executing thread is provided as a
     * parameter.
     * 
     * @param dict
     *            The pipeline dictionary to be used.
     * @throws PipeletExecutionException
     *             Thrown in case of severe errors that make the pipelet execute
     *             impossible (e.g. missing required input data).
     */
    public int execute(PipelineDictionary dict)
    throws PipeletExecutionException {        
        // lookup 'Product' in pipeline dictionary
        Product product = (Product)dict.get(DN_PRODUCT);
        if (null == product)
        {
            throw new PipeletExecutionException("Mandatory input parameter 'Product' not available in pipeline dictionary.");
        
        }
        
        // lookup 'Quantity' in pipeline dictionary
        Integer quantity = (Integer)dict.get(DN_QUANTITY);
        
        // lookup 'StoreList' in pipeline dictionary
        @SuppressWarnings("unchecked")
        List<Storefront> storeList = (List<Storefront>)dict.get(DN_STORE_FRONTS);
        if (null == storeList)
        {
            throw new PipeletExecutionException("Mandatory input parameter 'StoreList' not available in pipeline dictionary.");
        
        }
        
        // lookup 'CurrentOrganization' in pipeline dictionary
        Organization currentOrganization = (Organization)dict.get(DN_CURRENT_ORGANIZATION);
        if (null == currentOrganization)
        {
            throw new PipeletExecutionException(
                            "Mandatory input parameter 'CurrentOrganization' not available in pipeline dictionary.");
        }
        
        final Domain prefDomain = currentOrganization.getOwningDomain();
        ComponentMgr componentMgr = NamingMgr.getManager(ComponentMgr.class);
        MultichannelInventoryServiceResolver mcInvServiceResolver = 
            componentMgr.getComponent("multichannelInventoryServiceResolver");
        
        if (mcInvServiceResolver == null) {
            throw new PipeletExecutionException("Mandatory 'MultichannelInventoryServiceResolver' not available from Component Framework");
        }
        
        MultichannelInventoryService mcInvService = null;
        try {
            mcInvService = mcInvServiceResolver.getMultichannelInventoryService(prefDomain);
        } catch (Exception e) {
            Logger.error(this, e.getMessage());
        }
        
        if (mcInvService == null) {
            throw new PipeletExecutionException("Mandatory 'MultichannelInventoryService' not available for domain " + prefDomain.getDomainName());
        }
        
        //Create the quantity request
        InStoreQuantityRequest request = new InStoreQuantityRequest();
        request.setSku(product.getSKU());
        for (Storefront storefront : storeList) {
            request.addStorefrontId(Long.valueOf(storefront.getId()).intValue());
        }
        
        InStoreQuantityResponse response = mcInvService.getInStoreQuantities(request);
        Map<String, Integer> storefrontQuantityMap = response.getStoreFrontQuantityMap();
        
        
        dict.put(DN_STOREFRONT_QUANTITY_MAP, storefrontQuantityMap);
        return PIPELET_NEXT;
    }
}
